import dicomParser from 'dicom-parser';

class DicomService {
  static async loadDicomSeries(files) {
    // 如果只有一个文件，尝试作为多帧DICOM处理
    if (files.length === 1) {
      return await this.loadMultiFrameDicom(files[0]);
    }
    
    // 多文件处理逻辑保持不变
    const images = [];
    const seriesData = {
      images: [],
      metadata: {},
      seriesInstanceUID: null
    };

    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      try {
        const arrayBuffer = await this.readFileAsArrayBuffer(file);
        const dataSet = dicomParser.parseDicom(new Uint8Array(arrayBuffer));
        
        // 提取像素数据并创建图像URL
        const pixelDataInfo = await this.extractPixelData(dataSet);
        const imageId = this.createImageDataURL(pixelDataInfo);
        
        // 提取DICOM标签信息
        const imageData = {
          imageId: imageId,
          instanceNumber: this.getTagValue(dataSet, 'x00200013') || i + 1,
          seriesInstanceUID: this.getTagValue(dataSet, 'x0020000e'),
          studyInstanceUID: this.getTagValue(dataSet, 'x0020000d'),
          patientName: this.getTagValue(dataSet, 'x00100010'),
          studyDate: this.getTagValue(dataSet, 'x00080020'),
          modality: this.getTagValue(dataSet, 'x00080060'),
          rows: this.getTagValue(dataSet, 'x00280010'),
          columns: this.getTagValue(dataSet, 'x00280011'),
          pixelSpacing: this.getTagValue(dataSet, 'x00280030'),
          sliceThickness: this.getTagValue(dataSet, 'x00180050'),
          acquisitionTime: this.getTagValue(dataSet, 'x00080032'),
          fileName: file.name, // 保存原始文件名
          dataSet: dataSet
        };

        seriesData.images.push(imageData);
        
        // 设置系列元数据
        if (i === 0) {
          seriesData.seriesInstanceUID = imageData.seriesInstanceUID;
          seriesData.metadata = {
            // 患者信息
            patientName: imageData.patientName,
            patientId: this.getTagValue(dataSet, 'x00100020'),
            patientBirthDate: this.getTagValue(dataSet, 'x00100030'),
            patientSex: this.getTagValue(dataSet, 'x00100040'),
            // 检查信息
            studyDate: imageData.studyDate,
            studyTime: this.getTagValue(dataSet, 'x00080030'),
            studyDescription: this.getTagValue(dataSet, 'x00081030'),
            studyInstanceUID: imageData.studyInstanceUID,
            accessionNumber: this.getTagValue(dataSet, 'x00080050'),
            // 序列信息
            modality: imageData.modality,
            seriesDescription: this.getTagValue(dataSet, 'x0008103e'),
            seriesNumber: this.getTagValue(dataSet, 'x00200011'),
            bodyPartExamined: this.getTagValue(dataSet, 'x00180015'),
            // 医院信息
            institutionName: this.getTagValue(dataSet, 'x00080080'),
            institutionAddress: this.getTagValue(dataSet, 'x00080081'),
            stationName: this.getTagValue(dataSet, 'x00081010'),
            departmentName: this.getTagValue(dataSet, 'x00081040'),
            // 设备厂家信息
            manufacturer: this.getTagValue(dataSet, 'x00080070'),
            manufacturerModelName: this.getTagValue(dataSet, 'x00081090'),
            deviceSerialNumber: this.getTagValue(dataSet, 'x00181000'),
            softwareVersions: this.getTagValue(dataSet, 'x00181020'),
            // 图像参数
            rows: imageData.rows,
            columns: imageData.columns,
            pixelSpacing: imageData.pixelSpacing,
            sliceThickness: imageData.sliceThickness,
            // 采集参数
            repetitionTime: this.getTagValue(dataSet, 'x00180080'),
            echoTime: this.getTagValue(dataSet, 'x00180081'),
            flipAngle: this.getTagValue(dataSet, 'x00181314'),
            frameTime: this.getTagValue(dataSet, 'x00181063'),
            temporalResolution: this.getTagValue(dataSet, 'x00200110'),
            frameRate: this.getTagValue(dataSet, 'x00082144'),
            // 文件信息
            originalFileName: file.name,
            fileCount: files.length
          };
        }
      } catch (error) {
        console.error(`解析DICOM文件失败 ${file.name}:`, error);
        throw new Error(`无法解析DICOM文件: ${file.name}`);
      }
    }

    // 按实例号排序
    seriesData.images.sort((a, b) => 
      parseInt(a.instanceNumber) - parseInt(b.instanceNumber)
    );

    console.log('DICOM序列加载完成:', seriesData);
    return seriesData;
  }

  // 新增：处理多帧DICOM文件（如DSA图像）
  static async loadMultiFrameDicom(file) {
    try {
      const arrayBuffer = await this.readFileAsArrayBuffer(file);
      const dataSet = dicomParser.parseDicom(new Uint8Array(arrayBuffer));
      
      // 获取帧数
      const numberOfFrames = this.getTagValue(dataSet, 'x00280008') || 1;
      console.log('检测到多帧DICOM文件，帧数:', numberOfFrames);
      
      const rows = this.getTagValue(dataSet, 'x00280010');
      const columns = this.getTagValue(dataSet, 'x00280011');
      const bitsAllocated = this.getTagValue(dataSet, 'x00280100') || 16;
      
      // 提取基本元数据
      const baseMetadata = {
        // 患者信息
        patientName: this.getTagValue(dataSet, 'x00100010'),
        patientId: this.getTagValue(dataSet, 'x00100020'),
        patientBirthDate: this.getTagValue(dataSet, 'x00100030'),
        patientSex: this.getTagValue(dataSet, 'x00100040'),
        // 检查信息
        studyDate: this.getTagValue(dataSet, 'x00080020'),
        studyTime: this.getTagValue(dataSet, 'x00080030'),
        studyDescription: this.getTagValue(dataSet, 'x00081030'),
        studyInstanceUID: this.getTagValue(dataSet, 'x0020000d'),
        accessionNumber: this.getTagValue(dataSet, 'x00080050'),
        // 序列信息
        modality: this.getTagValue(dataSet, 'x00080060'),
        seriesDescription: this.getTagValue(dataSet, 'x0008103e'),
        seriesNumber: this.getTagValue(dataSet, 'x00200011'),
        bodyPartExamined: this.getTagValue(dataSet, 'x00180015'),
        // 医院信息
        institutionName: this.getTagValue(dataSet, 'x00080080'),
        institutionAddress: this.getTagValue(dataSet, 'x00080081'),
        stationName: this.getTagValue(dataSet, 'x00081010'),
        departmentName: this.getTagValue(dataSet, 'x00081040'),
        // 设备厂家信息
        manufacturer: this.getTagValue(dataSet, 'x00080070'),
        manufacturerModelName: this.getTagValue(dataSet, 'x00081090'),
        deviceSerialNumber: this.getTagValue(dataSet, 'x00181000'),
        softwareVersions: this.getTagValue(dataSet, 'x00181020'),
        // 图像参数
        rows: rows,
        columns: columns,
        pixelSpacing: this.getTagValue(dataSet, 'x00280030'),
        sliceThickness: this.getTagValue(dataSet, 'x00180050'),
        numberOfFrames: numberOfFrames,
        // 采集参数
        repetitionTime: this.getTagValue(dataSet, 'x00180080'),
        echoTime: this.getTagValue(dataSet, 'x00180081'),
        flipAngle: this.getTagValue(dataSet, 'x00181314'),
        frameTime: this.getTagValue(dataSet, 'x00181063'),
        temporalResolution: this.getTagValue(dataSet, 'x00200110'),
        frameRate: this.getTagValue(dataSet, 'x00082144')
      };
      
      // 提取所有帧的像素数据
      const allFramesPixelData = await this.extractMultiFramePixelData(dataSet, numberOfFrames);
      
      const seriesData = {
        images: [],
        metadata: baseMetadata,
        seriesInstanceUID: this.getTagValue(dataSet, 'x0020000e'),
        isMultiFrame: true
      };
      
      // 为每一帧创建图像数据
      for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
        const framePixelData = allFramesPixelData[frameIndex];
        // 如果某一帧的数据为空（可能在提取时发生错误），则跳过
        if (!framePixelData) {
            console.warn(`Skipping frame ${frameIndex} due to missing pixel data.`);
            continue;
        }
        const imageId = this.createImageDataURL({
          data: framePixelData,
          rows: rows,
          columns: columns,
          bitsAllocated: bitsAllocated
        });
        
        const imageData = {
          imageId: imageId,
          instanceNumber: frameIndex + 1,
          frameNumber: frameIndex,
          rows: rows,
          columns: columns,
          fileName: file.name, // 保存原始文件名
          dataSet: {
            pixelData: framePixelData, // 原始像素数据用于处理
            elements: dataSet.elements  // 保留原始DICOM标签
          },
          acquisitionTime: this.getFrameAcquisitionTime(dataSet, frameIndex),
          ...baseMetadata
        };
        
        seriesData.images.push(imageData);
      }
      
      // 在元数据中添加文件信息
      seriesData.metadata.originalFileName = file.name;
      seriesData.metadata.fileCount = 1; // 单个多帧文件
      
      console.log('多帧DICOM文件加载完成:', seriesData);
      return seriesData;
      
    } catch (error) {
      console.error('加载多帧DICOM文件失败:', error);
      throw new Error(`无法解析多帧DICOM文件: ${file.name}`);
    }
  }

  // 新增：提取多帧像素数据
  static async extractMultiFramePixelData(dataSet, numberOfFrames) {
    try {
      const pixelDataElement = dataSet.elements.x7fe00010;
      if (!pixelDataElement) {
        throw new Error('未找到像素数据');
      }

      // 新增：检查文件是否为不支持的压缩格式
      // 在DICOM标准中，压缩过的图像其像素数据是“封装”的（encapsulated）。
      if (pixelDataElement.encapsulatedPixelData) {
        const transferSyntax = this.getTagValue(dataSet, 'x00020010') || 'Unknown';
        console.error(`Unsupported encapsulated/compressed pixel data. Transfer Syntax: ${transferSyntax}`);
        // 抛出更明确的错误，告知用户文件是压缩的
        throw new Error(`The DICOM file is compressed (Transfer Syntax: ${transferSyntax}), which is not supported by this viewer.`);
      }

      const rows = this.getTagValue(dataSet, 'x00280010');
      const columns = this.getTagValue(dataSet, 'x00280011');
      const bitsAllocated = this.getTagValue(dataSet, 'x00280100') || 16;
      const samplesPerPixel = this.getTagValue(dataSet, 'x00280002') || 1;
      
      const pixelsPerFrame = rows * columns * samplesPerPixel;
      const bytesPerPixel = bitsAllocated / 8;
      const bytesPerFrame = pixelsPerFrame * bytesPerPixel;
      
      let sourcePixelData;
      if (bitsAllocated === 16) {
        sourcePixelData = new Uint16Array(
          dataSet.byteArray.buffer,
          pixelDataElement.dataOffset,
          pixelDataElement.length / 2
        );
      } else {
        sourcePixelData = new Uint8Array(
          dataSet.byteArray.buffer,
          pixelDataElement.dataOffset,
          pixelDataElement.length
        );
      }
      
      console.log(`提取多帧像素数据: ${numberOfFrames}帧, 每帧${pixelsPerFrame}像素`);
      
      const frames = [];
      for (let frameIndex = 0; frameIndex < numberOfFrames; frameIndex++) {
        const startOffset = frameIndex * pixelsPerFrame;
        const endOffset = startOffset + pixelsPerFrame;
        
        if (endOffset <= sourcePixelData.length) {
          const frameData = sourcePixelData.slice(startOffset, endOffset);
          frames.push(frameData);
        } else {
          console.warn(`帧 ${frameIndex} 数据不完整，可能是文件截断或解析错误，已跳过`);
          // 用 null 填充数组以保持帧总数，避免后续循环出错
          frames.push(null); 
        }
      }
      
      console.log(`成功提取 ${frames.filter(f => f).length} 帧有效像素数据`);
      return frames;
      
    } catch (error) {
      console.error('提取多帧像素数据失败:', error);
      throw error;
    }
  }

  // 新增：获取帧的采集时间（如果有的话）
  static getFrameAcquisitionTime(dataSet, frameIndex) {
    try {
      // 优先从帧率标签 (0008,2144) 获取 - Recommended Display Frame Rate
      const frameRate = this.getTagValue(dataSet, 'x00082144');
      if (frameRate && parseFloat(frameRate) > 0) {
        const framesPerSecond = parseFloat(frameRate);
        const timeInterval = 1.0 / framesPerSecond; // 每帧的时间间隔（秒）
        console.log(`使用DICOM帧率信息: ${framesPerSecond} fps, 时间间隔: ${timeInterval.toFixed(3)}s`);
        return frameIndex * timeInterval;
      }
      
      // 尝试从Frame Time Vector (0018,1065) 获取 - 这是标准的多帧时间标签
      const frameTimeVector = this.getTagValue(dataSet, 'x00181065');
      if (frameTimeVector && Array.isArray(frameTimeVector) && frameTimeVector[frameIndex] !== undefined) {
        return parseFloat(frameTimeVector[frameIndex]);
      }
      
      // 尝试从Frame Time (0018,1063) 获取
      const frameTime = this.getTagValue(dataSet, 'x00181063');
      if (frameTime) {
        const frameTimeMs = parseFloat(frameTime);
        console.log(`使用Frame Time信息: ${frameTimeMs}ms 间隔`);
        return frameIndex * (frameTimeMs / 1000); // 转换为秒
      }
      
      // 尝试从Temporal Resolution (0020,0110) 计算
      const temporalResolution = this.getTagValue(dataSet, 'x00200110');
      if (temporalResolution) {
        const intervalMs = parseFloat(temporalResolution);
        console.log(`使用Temporal Resolution信息: ${intervalMs}ms 间隔`);
        return frameIndex * intervalMs / 1000; // 转换为秒
      }
      
      // 尝试从Acquisition Time (0008,0032) 获取基础时间
      const baseTime = this.getTagValue(dataSet, 'x00080032');
      if (baseTime) {
        // DSA/造影序列通常每帧间隔约0.5-2秒
        const estimatedInterval = 1.0; // 默认1秒间隔
        console.log(`使用默认估计间隔: ${estimatedInterval}s`);
        return frameIndex * estimatedInterval;
      }
      
      // 最后兜底：使用帧索引，假设每帧1秒
      console.log(`兜底使用1秒间隔`);
      return frameIndex * 1.0;
    } catch (error) {
      console.warn(`获取帧 ${frameIndex} 采集时间失败:`, error);
      return frameIndex * 1.0; // 兜底返回帧索引秒数
    }
  }

  static createImageDataURL(pixelDataInfo) {
    try {
      const { data, rows, columns, bitsAllocated } = pixelDataInfo;
      
      // 创建Canvas
      const canvas = document.createElement('canvas');
      canvas.width = columns;
      canvas.height = rows;
      const ctx = canvas.getContext('2d');
      
      const imageData = ctx.createImageData(columns, rows);
      const pixels = imageData.data;
      
      // 转换像素数据
      let maxValue = 0;
      let minValue = Infinity;
      
      // 找到最大值和最小值用于归一化
      for (let i = 0; i < data.length; i++) {
        const value = data[i];
        if (value > maxValue) maxValue = value;
        if (value < minValue) minValue = value;
      }
      
      const range = maxValue - minValue;
      
      // 转换为8位灰度图像
      for (let i = 0; i < data.length && i < columns * rows; i++) {
        let normalizedValue;
        if (range === 0) {
          normalizedValue = 128; // 中间灰度
        } else {
          normalizedValue = Math.round(((data[i] - minValue) / range) * 255);
        }
        
        pixels[i * 4] = normalizedValue;     // Red
        pixels[i * 4 + 1] = normalizedValue; // Green
        pixels[i * 4 + 2] = normalizedValue; // Blue
        pixels[i * 4 + 3] = 255;             // Alpha
      }
      
      ctx.putImageData(imageData, 0, 0);
      
      console.log(`创建DICOM图像URL: ${columns}x${rows}, 范围: ${minValue}-${maxValue}`);
      return canvas.toDataURL();
    } catch (error) {
      console.error('创建图像URL失败:', error);
      throw error;
    }
  }

  static readFileAsArrayBuffer(file) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = (event) => resolve(event.target.result);
      reader.onerror = (error) => reject(error);
      reader.readAsArrayBuffer(file);
    });
  }

  static getTagValue(dataSet, tag) {
    try {
      const element = dataSet.elements[tag];
      if (!element) return null;

      if (element.vr === 'US' || element.vr === 'SS') {
        return dataSet.uint16(tag);
      } else if (element.vr === 'UL' || element.vr === 'SL') {
        return dataSet.uint32(tag);
      } else if (element.vr === 'FL') {
        return dataSet.float(tag);
      } else if (element.vr === 'FD') {
        return dataSet.double(tag);
      } else if (element.vr === 'DS') {
        const str = dataSet.string(tag);
        return str ? parseFloat(str.split('\\')[0]) : null;
      } else if (element.vr === 'IS') {
        const str = dataSet.string(tag);
        return str ? parseInt(str.split('\\')[0]) : null;
      } else {
        const str = dataSet.string(tag);
        return str ? str.split('\\')[0] : null;
      }
    } catch (error) {
      console.warn(`获取DICOM标签 ${tag} 失败:`, error);
      return null;
    }
  }

  static async extractPixelData(dataSet) {
    try {
      const pixelDataElement = dataSet.elements.x7fe00010;
      if (!pixelDataElement) {
        throw new Error('未找到像素数据');
      }

      const rows = this.getTagValue(dataSet, 'x00280010');
      const columns = this.getTagValue(dataSet, 'x00280011');
      const bitsAllocated = this.getTagValue(dataSet, 'x00280100') || 16;
      const bitsStored = this.getTagValue(dataSet, 'x00280101') || 16;
      const pixelRepresentation = this.getTagValue(dataSet, 'x00280103') || 0;

      let pixelData;
      if (bitsAllocated === 16) {
        pixelData = new Uint16Array(
          dataSet.byteArray.buffer,
          pixelDataElement.dataOffset,
          pixelDataElement.length / 2
        );
      } else {
        pixelData = new Uint8Array(
          dataSet.byteArray.buffer,
          pixelDataElement.dataOffset,
          pixelDataElement.length
        );
      }

      return {
        data: pixelData,
        rows: rows,
        columns: columns,
        bitsAllocated: bitsAllocated,
        bitsStored: bitsStored,
        pixelRepresentation: pixelRepresentation
      };
    } catch (error) {
      console.error('提取像素数据失败:', error);
      throw error;
    }
  }

  static validateDicomFile(file) {
    return file.name.toLowerCase().endsWith('.dcm') || 
           file.name.toLowerCase().endsWith('.dicom') ||
           file.type === 'application/dicom';
  }
}

export { DicomService }; 